using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Mail;
using System.Text;
using JetBrains.Annotations;
using Kaleida.ServiceMonitor.Framework;

namespace Kaleida.ServiceMonitor.Model.Runtime
{
    public class CompiledScriptModule
    {
        private Duration pollInterval = CompiledScript.DefaultPollInterval;
        private Duration maximumErrorAge = new Duration(100, "days");

        private readonly List<IOperation> operations = new List<IOperation>();
        private OperationOrder executionOrder = new RoundRobinOperationOrder();
        private IList<MailAddress> emailOnThresholdChangeRecipients = new List<MailAddress>();
        private EmailSummarySchedule emailSummarySchedule = new EmailSummarySchedule(Enumerable.Empty<MailAddress>(), Enumerable.Empty<ScheduledTime>());
        private IStateColourationStrategy colourationStrategy = new StateColourationStrategy();
        private string name;
        private Guid id;
        public event EventHandler PollIntervalChanged;

        public CompiledScriptModule(string name)
        {
            this.name = name;
            this.id = Guid.NewGuid();
        }

        [NotNull]
        public string Name
        {
            get { return name; }
            internal set
            {
                if (value == null) throw new ArgumentNullException("value");
                name = value;
            }
        }

        public Guid Id
        {
            get { return id; }
        }

        public List<IOperation> Operations
        {
            get { return operations; }
        }

        public OperationOrder ExecutionOrder
        {
            get { return executionOrder; }
            internal set { executionOrder = value; }
        }

        [NotNull]
        public Duration PollInterval
        {
            get { return pollInterval; }
            internal set
            {
                if (value == null) throw new ArgumentNullException("value");

                pollInterval = PollIntervalCriteria.EnsureMet(value);

                if (PollIntervalChanged != null)
                    PollIntervalChanged(this, EventArgs.Empty);
            }
        }

        [NotNull]
        internal IList<MailAddress> EmailOnThresholdChangeRecipients
        {
            get { return emailOnThresholdChangeRecipients; }
            set
            {
                if (value == null) throw new ArgumentNullException("value");
                emailOnThresholdChangeRecipients = value;
            }
        }

        [NotNull]
        public EmailSummarySchedule EmailSummarySchedule
        {
            get { return emailSummarySchedule; }
            internal set
            {
                if (value == null) throw new ArgumentNullException("value");
                emailSummarySchedule = value;
            }
        }

    	[NotNull]
    	public Duration MaximumErrorAge
    	{
			get { return maximumErrorAge; }
            internal set
			{
				if (value == null) throw new ArgumentNullException("value");
				maximumErrorAge = value;
			}
    	}

        [NotNull]
        public IStateColourationStrategy ColourationStrategy
        {
            get { return colourationStrategy; }
            set
            {
                if (value == null) throw new ArgumentNullException("value");
                colourationStrategy = value;
            }
        }

        public string BuildSummary()
        {
            var summary = new StringBuilder();
            summary.AppendFormat("Module '{0}':\r\n", Name);
            summary.AppendFormat("  {0} operation{1} performed ", Operations.Count(), Operations.Count() == 1 ? "" : "s");
            summary.AppendFormat("in {0} order, with {1} between each invocation\r\n", ExecutionOrder.Name, PollInterval);
            summary.AppendFormat("  The maximum age of any error is {0}.\r\n", maximumErrorAge);

            if (emailOnThresholdChangeRecipients.Any())
            {
                summary.Append("  When the monitor colour changes, emails will be sent to: ");
                summary.Append(String.Join("; ", emailOnThresholdChangeRecipients));
                summary.AppendLine();
            }

            if (emailSummarySchedule.Recipients.Any())
            {
                var timesOfDaySummary = String.Join(", ", emailSummarySchedule.Times);
                summary.AppendFormat("  At {0} every day, a summary email will be sent to: ", timesOfDaySummary);
                summary.Append(String.Join("; ", emailSummarySchedule.Recipients));
                summary.AppendLine();
            }

            summary.AppendFormat("  Colour thresholds: {0}\r\n", colourationStrategy.Description);
            summary.AppendLine();

            return summary.ToString();
        }
    }
}